/*
 * SysReport.java
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package utils;

import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.*;
import java.text.DecimalFormat;
import javax.imageio.ImageIO;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import persistence.PersistFactory;
import persistence.dao.FilesystemDao;
import persistence.services.PersistenceException;

/**
 *
 * @author gurgel
 */
public class SmReport {

    private static final Log log = LogFactory.getLog(SmReport.class);
    private PrintStream console = System.out;
    private SmPdf pdf;
    private String baseFolder;
    private boolean fileOpen = false;
    private boolean convertNewLine = false;
    private boolean nowrap = true;
    private int border = 0;
    private String tableHeader = "<table cellspacing=%d cellpadding=%d border=%d align=center width=100%%>";

    /**
     * Creates a new instance of SysReport
     */
    public SmReport() { 
    }

    /**
     * open htm and pdf files, change the default output to the files. create the folder and file if needed.
     *
     * @param nmFolder
     * @param nmFileBase without the file extention
     * @param createPdf
     */
    public void doOutputToFile(String nmFolder, String nmFileBase, boolean createPdf) throws PersistenceException {
        this.baseFolder = nmFolder;
        //define base name for pdf and htm
        String nmBaseFile = getBaseFolder() + nmFileBase;
        //define htm filename
        String nmFileHtml = nmBaseFile + ".htm";

        //create folder if not there
        if (!PersistFactory.getFilesystemDao().createFolder(nmFolder)
                || !PersistFactory.getFilesystemDao().createStream(nmFileHtml)) {
            throw new PersistenceException(String.format("Not able to create output file %s at folder %s.", nmFolder, nmFileBase));
        }
        //initialize HTML code. could be fancier...
        this.printHtml("<html><body><pre>");
        //prepara PDF
        if (createPdf) {
            String nmFilePdf = nmBaseFile + ".pdf";
            this.setPdf(new SmPdf(nmFilePdf));
        }
        //set flag that there are open files.
        this.setFileOpen(true);
    }

    /**
     * close files and change the output back to console
     */
    public void close() {
        if (this.isFileOpen()) {
            this.printHtml("</pre></body></html>");
            if (this.isPdfActive()) {
                this.getPdf().closePdf();
            }
        }
        System.setOut(this.getConsole());
        this.setFileOpen(false);
    }

    public String getImagesFolderFullPath() {
        return getBaseFolder() + FilesystemDao.IMAGES_FOLDER;
    }

    public String getImagesFolderRelative() {
        return FilesystemDao.IMAGES_FOLDER;
    }

    private void saveImage(RenderedImage rendImage, String nmFile) {
        // Write generated image to a file
        try {
            // Save as PNG
            File file = new File(this.getImagesFolderFullPath() + nmFile);
            ImageIO.write(rendImage, "png", file);
        } catch (java.io.FileNotFoundException ex) {
            log.error("Trouble saving image: " + nmFile);
            throw new UnsupportedOperationException("Trouble saving image to folder: " + nmFile, ex);
        } catch (IOException ex) {
            log.error("Trouble saving image: " + nmFile, ex);
        }
    }

    public DecimalFormat getMyFormatter() {
        return (SmUtils.getMyFormatter());
    }

    public PrintStream getConsole() {
        return console;
    }

    public void setConsole(PrintStream console) {
        this.console = console;
    }

    public SmPdf getPdf() {
        return pdf;
    }

    public void setPdf(SmPdf pdf) {
        this.pdf = pdf;
    }

    public boolean isPdfActive() {
        try {
            return this.getPdf().isPdfActive();
        } catch (NullPointerException e) {
            return false;
        }
    }

    public void writeImg(BufferedImage image, String nmFile) {
        this.saveImage(image, nmFile);
        this.printHtml(String.format("<p align='center'><img src=%s%s></p>", getImagesFolderRelative(), nmFile));
        if (this.isPdfActive()) {
            this.getPdf().writeImg(image);
        }
    }

    public void write(String text) {
        if (!text.equals("")) {
            this.printHtml(text);
            if (this.isPdfActive()) {
                this.getPdf().write(text);
            }
        }
    }

    public void writeBold(String text) {
        if (!text.equals("")) {
            this.printHtml(String.format("<b>%s</b>", text));
            if (this.isPdfActive()) {
                this.getPdf().write(text, true);
            }
        }
    }

    public void writeBoldFirstLine(String text) {
        if (!text.equals("")) {
            String[] rows = text.split("\n", 2);
            boolean first = true;
            for (String texto : rows) {
                if (first) {
                    this.writeBold(texto);
                    first = false;
                } else {
                    this.write(texto);
                }
            }
        }
    }

    public void writeTitle(String text) {
        this.printHtml("<h2><div align=Center>" + text + "</div></h2>");
        if (this.isPdfActive()) {
            this.getPdf().writeTitle(text);
        }
    }

    public void newLine() {
        SmUtils.print();
        if (this.isPdfActive()) {
            this.getPdf().write();
        }
    }

    public void newPage() {
        if (this.isPdfActive()) {
            this.getPdf().newPage();
        }
    }

    public void lineSeparator() {
        String lineSeparator = "\n<hr>\n";
        this.printHtml(lineSeparator);
        if (this.isPdfActive()) {
            this.getPdf().write();
        }
    }

    public void writeTable(float[] qtCols) {
        this.printHtml(String.format(tableHeader, 2, 2, getBorder()));
        if (this.isPdfActive()) {
            this.getPdf().writeTable(qtCols);
        }
        this.writeTableRow();
    }

    public void writeTable(int qtCols) {
        this.printHtml(String.format(tableHeader, 2, 2, getBorder()));
        if (this.isPdfActive()) {
            this.getPdf().writeTable(qtCols);
        }
        this.writeTableRow();
    }

    public void writeCellPre(String text) {
        this.printHtml(String.format("<td %s><pre>%s</pre></td>", getNowrap(), text));
        if (this.isPdfActive()) {
            this.getPdf().writeCell(text);
        }
    }

    public void writeCell(String text) {
        this.printHtml(String.format("<td %s>%s</td>", getNowrap(), text));
        if (this.isPdfActive()) {
            this.getPdf().writeCell(text);
        }
    }

    public void writeCellTitletImg(String text, String nmFile) {
        this.printHtml(String.format("<td %s><h2><div align=Center>%s</div></h2>%s<br>\n<img src=%s%s>\n",
                getNowrap(), text, getImagesFolderRelative(), nmFile));
        if (this.isPdfActive()) {
            this.getPdf().writeCellTitletImg(text, getImagesFolderFullPath() + nmFile);
        }
    }

    public void writeTableRow() {
        this.printHtml("<tr>");
//        if(this.isPdfActive()) {
//            this.getPdf().write();
//        }
    }

    public void writeTableClose() {
        this.printHtml("</table>");
        if (this.isPdfActive()) {
            this.getPdf().writeTableClose();
        }
    }

    public void writeNestedTable(float[] qtColunas) {
        this.printHtml(String.format("<td>" + tableHeader, 0, 0, getBorder()));
        if (this.isPdfActive()) {
            this.getPdf().writeNestedTable(qtColunas);
        }
        this.writeNextedTableRow();
    }

    public void writeNestedTable(int qtColunas) {
        this.printHtml(String.format("<td>" + tableHeader, 0, 0, getBorder()));
        if (this.isPdfActive()) {
            this.getPdf().writeNestedTable(qtColunas);
        }
        this.writeNextedTableRow();
    }

    public void writeNestedCell(String texto) {
        this.printHtml("<td " + getNowrap() + ">" + texto + "</td>");
        if (this.isPdfActive()) {
            this.getPdf().writeNestedCell(texto);
        }
    }

    public void writeNestedCellBold(String texto) {
        this.printHtml("<td " + getNowrap() + "><b>" + texto + "</b></td>");
        if (this.isPdfActive()) {
            this.getPdf().writeNestedCellBold(texto);
        }
    }

    public void writeNextedTableRow() {
        this.printHtml("<tr>");
//        if(this.isPdfActive()) {
//            this.getPdf().write();
//        }
    }

    public void writeNestedTableClose() {
        this.printHtml("</table>");
        if (this.isPdfActive()) {
            this.getPdf().writeNestedTableClose();
        }
    }

    public void writeCellBold(String texto) {
        this.printHtml("<td " + getNowrap() + "><b>" + texto + "</b></td>");
        if (this.isPdfActive()) {
            this.getPdf().writeCellBold(texto);
        }
    }

    private String getBaseFolder() {
        return this.baseFolder;
    }

    /**
     * @return the fileOpen
     */
    private boolean isFileOpen() {
        return fileOpen;
    }

    /**
     * @param isfileopen the fileOpen to set
     */
    private void setFileOpen(boolean isfileopen) {
        this.fileOpen = isfileopen;
    }

    /**
     * @return the border
     */
    public int getBorder() {
        return border;
    }

    /**
     * can only be user after cosoleDesvia
     *
     * @param border the border to set
     */
    public void setBorder(int border) {
        this.border = border;
        this.getPdf().setBorder(border);
    }

    /**
     * @return the nowrap
     */
    public boolean isNowrap() {
        return nowrap;
    }

    /**
     * @param nowrap the nowrap to set
     */
    public void setNowrap(boolean nowrap) {
        this.nowrap = nowrap;
    }

    private String getNowrap() {
        if (nowrap) {
            return "nowrap";
        } else {
            return "";
        }
    }

    private void printHtml(String text) {
        System.out.println(this.ascToHtml(text));
    }

    private void printHtml(int text) {
        System.out.println(text);
    }

    private void printHtml(long text) {
        System.out.println(text);
    }

    /**
     * @return the convertNewLine
     */
    public boolean isConvertNewLine() {
        return convertNewLine;
    }

    /**
     * @param convertNewLine the convertNewLine to set
     */
    public void setConvertNewLine(boolean convertNewLine) {
        this.convertNewLine = convertNewLine;
    }

    public String ascToHtml(String original) {
        String ret = original;
        ret = ret.replaceAll("À", "&Agrave;");
        ret = ret.replaceAll("Á", "&Aacute;");
        ret = ret.replaceAll("Â", "&Acirc;");
        ret = ret.replaceAll("Ã", "&Atilde;");
        ret = ret.replaceAll("Ä", "&Auml;");
        ret = ret.replaceAll("Å", "&Aring;");
        ret = ret.replaceAll("Æ", "&AElig;");
        ret = ret.replaceAll("Ç", "&Ccedil;");
        ret = ret.replaceAll("È", "&Egrave;");
        ret = ret.replaceAll("É", "&Eacute;");
        ret = ret.replaceAll("Ê", "&Ecirc;");
        ret = ret.replaceAll("Ë", "&Euml;");
        ret = ret.replaceAll("Ì", "&Igrave;");
        ret = ret.replaceAll("Í", "&Iacute;");
        ret = ret.replaceAll("Î", "&Icirc;");
        ret = ret.replaceAll("Ï", "&Iuml;");
        ret = ret.replaceAll("Ð", "&ETH;");
        ret = ret.replaceAll("Ñ", "&Ntilde;");
        ret = ret.replaceAll("Œ", "&OElig;");
        ret = ret.replaceAll("Ò", "&Ograve;");
        ret = ret.replaceAll("Ó", "&Oacute;");
        ret = ret.replaceAll("Ô", "&Ocirc;");
        ret = ret.replaceAll("Õ", "&Otilde;");
        ret = ret.replaceAll("Ö", "&Ouml;");
        ret = ret.replaceAll("Ø", "&Oslash;");
        ret = ret.replaceAll("Š", "&Scaron;");
        ret = ret.replaceAll("Ù", "&Ugrave;");
        ret = ret.replaceAll("Ú", "&Uacute;");
        ret = ret.replaceAll("Û", "&Ucirc;");
        ret = ret.replaceAll("Ü", "&Uuml;");
        ret = ret.replaceAll("Ý", "&Yacute;");
        ret = ret.replaceAll("Þ", "&THORN;");
        ret = ret.replaceAll("Ÿ", "&Yuml;");
        ret = ret.replaceAll("à", "&agrave;");
        ret = ret.replaceAll("á", "&aacute;");
        ret = ret.replaceAll("â", "&acirc;");
        ret = ret.replaceAll("ã", "&atilde;");
        ret = ret.replaceAll("ä", "&auml;");
        ret = ret.replaceAll("å", "&aring;");
        ret = ret.replaceAll("æ", "&aelig;");
        ret = ret.replaceAll("ç", "&ccedil;");
        ret = ret.replaceAll("è", "&egrave;");
        ret = ret.replaceAll("é", "&eacute;");
        ret = ret.replaceAll("ê", "&ecirc;");
        ret = ret.replaceAll("ë", "&euml;");
        ret = ret.replaceAll("ì", "&igrave;");
        ret = ret.replaceAll("í", "&iacute;");
        ret = ret.replaceAll("î", "&icirc;");
        ret = ret.replaceAll("ï", "&iuml;");
        ret = ret.replaceAll("ð", "&eth;");
        ret = ret.replaceAll("ñ", "&ntilde;");
        ret = ret.replaceAll("œ", "&oelig;");
        ret = ret.replaceAll("ò", "&ograve;");
        ret = ret.replaceAll("ó", "&oacute;");
        ret = ret.replaceAll("ô", "&ocirc;");
        ret = ret.replaceAll("õ", "&otilde;");
        ret = ret.replaceAll("ö", "&ouml;");
        ret = ret.replaceAll("ø", "&oslash;");
        ret = ret.replaceAll("š", "&scaron;");
        ret = ret.replaceAll("ù", "&ugrave;");
        ret = ret.replaceAll("ú", "&uacute;");
        ret = ret.replaceAll("û", "&ucirc;");
        ret = ret.replaceAll("ü", "&uuml;");
        ret = ret.replaceAll("ý", "&yacute;");
        ret = ret.replaceAll("þ", "&thorn;");
        ret = ret.replaceAll("ÿ", "&yuml;");
        if (isConvertNewLine()) {
            ret = ret.replaceAll("\n", "<br>");
        }
        return ret;
    }
}
